package com.heima.behavior.service.impl;

import com.alibaba.fastjson.JSON;
import com.heima.behavior.service.ApBehaviorEntryService;
import com.heima.behavior.service.ApLikesBehaviorService;
import com.heima.common.constants.article.HotArticleConstants;
import com.heima.common.exception.CustException;
import com.heima.model.behavior.dtos.LikesBehaviorDTO;
import com.heima.model.behavior.pojos.ApBehaviorEntry;
import com.heima.model.behavior.pojos.ApLikesBehavior;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.mess.app.NewBehaviorDTO;
import com.heima.model.threadlocal.AppThreadLocalUtils;
import com.heima.model.user.pojos.ApUser;
import com.mongodb.client.result.DeleteResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;

/**
 * @Author XHui
 * @Since 2024/2/22 9:04
 * @Version 1.0
 */
@Slf4j
@Service
public class ApLikesBehaviorServiceImpl implements ApLikesBehaviorService {

    @Resource
    private ApBehaviorEntryService apBehaviorEntryService;

    @Resource
    private MongoTemplate mongoTemplate;
    
    @Resource
    private RabbitTemplate rabbitTemplate;

    /**
     * 点赞行为
     * 1. 用户必须通过账号密码进行登录
     * 2.
     *
     * @param dto DTO
     * @return 通用的结果返回类
     */
    @Override
    public ResponseResult likes(LikesBehaviorDTO dto) {

        ApBehaviorEntry apBehaviorEntry = getApBehaviorEntry(dto);
        Integer operation = dto.getOperation();
        
        if (apBehaviorEntry == null) {
            // 用户和 设备ID 都不存在
            CustException.cust(AppHttpCodeEnum.DATA_NOT_ALLOW,
                    "用户和 设备ID 都不存在, 点赞行为失败");
        }

        //3. 根据 行为实体ID 和 articleId 查询点赞记录中是否存在
        Query query = new Query(
                Criteria.where("entryId").is(apBehaviorEntry.getId())
                        .and("articleId").is(dto.getArticleId())
        );
        ApLikesBehavior apLikesBehaviorDB = mongoTemplate.findOne(query, ApLikesBehavior.class);

        // 3.1 根据用户对文章的操作，计算文章得分
        NewBehaviorDTO newBehaviorDTO = new NewBehaviorDTO();
        newBehaviorDTO.setType(NewBehaviorDTO.BehaviorType.LIKES);
        int add = operation
                == ApLikesBehavior.Operation.LIKE.getValue() ? 1 : -1;
        newBehaviorDTO.setAdd(add);
        newBehaviorDTO.setArticleId(dto.getArticleId());

        
        // 4. 根据行为实体，插入数据 -> 集合ap_behavior_likes
        if (apLikesBehaviorDB == null &&
                operation == ApLikesBehavior.Operation.LIKE.getValue()) {
            sendUserOperationsToRabbitMQ(newBehaviorDTO);
            // 4.1 点赞记录不存在且是点赞行为，插入一条数据
            apLikesBehaviorDB = new ApLikesBehavior();
            apLikesBehaviorDB.setEntryId(apBehaviorEntry.getId());
            apLikesBehaviorDB.setArticleId(dto.getArticleId());
            apLikesBehaviorDB.setType(dto.getType());
            apLikesBehaviorDB.setOperation(ApLikesBehavior.Operation.LIKE.getValue());
            apLikesBehaviorDB.setCreatedTime(LocalDateTime.now());
            ApLikesBehavior behaviorLikes = mongoTemplate.save(apLikesBehaviorDB);
            return ResponseResult.okResult(behaviorLikes);
        } else if (apLikesBehaviorDB != null &&
                operation == ApLikesBehavior.Operation.UNLIKE.getValue()
        ) {
            sendUserOperationsToRabbitMQ(newBehaviorDTO);
            // 当前用户已经点过赞了，且是取消点赞行为，删除点赞记录
            DeleteResult remove = mongoTemplate.remove(apLikesBehaviorDB);
            
            if (remove.getDeletedCount() > 0) {
                return ResponseResult.okResult();
            } else {
                return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_ALLOW, "取消点赞操作失败");
            }
        }

        // 5. 重复操作
        if (ApLikesBehavior.Operation.LIKE.getValue() == operation) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_ALLOW, "重复点赞操作");
        } else {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_ALLOW, "重复取消点赞操作");
        }
    }

    void sendUserOperationsToRabbitMQ(NewBehaviorDTO newBehaviorDTO) {
        rabbitTemplate.convertAndSend(
                HotArticleConstants.HOT_ARTICLE_SCORE_BEHAVIOR_QUEUE,
                JSON.toJSONString(newBehaviorDTO)
                );
        log.info("点赞行为，发送消息到队列 -> {}", JSON.toJSONString(newBehaviorDTO));
    }

    private ApBehaviorEntry getApBehaviorEntry(LikesBehaviorDTO dto) {
        // 1. 判断当前用户是否真实登录
        ApUser user = AppThreadLocalUtils.getUser();
        if (user == null) {
            CustException.cust(AppHttpCodeEnum.DATA_NOT_ALLOW,
                    "用户未登录或通过设备登录，请使用账号密码登录");
        }
        if (user.getId() == 0) { // 通过设备登录
            return apBehaviorEntryService
                    .findByUserIdOrEquipmentId(
                            null, dto.getEquipmentId());
        }
        // 通过账号登录
        // 2. 查询当前用户的行为实体是否在MongoDB中存在
        Integer userId = user.getId();
        ApBehaviorEntry apBehaviorEntry = apBehaviorEntryService
                .findByUserIdOrEquipmentId(
                        userId, null);
        return apBehaviorEntry;
    }
}
